package controller

import (
	"equantum/common"
	"equantum/dto"
	"equantum/model"
	"equantum/response"
	"errors"
	"io/ioutil"

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
)

type IFileController interface {
	RestController           // 创建，重命名，文件列表，删除
	Upload(ctx *gin.Context) // 上传文件
	Save(ctx *gin.Context)   // 保存文件内容
	Load(ctx *gin.Context)   // 读取文件内容
}

type FileController struct {
	DB *gorm.DB
}

// TODO：初始化数据库，插入样例文件

func NewFileController() IFileController {
	db := common.GetDB()          // 获取数据库连接池
	db.AutoMigrate(&model.File{}) // 创建表

	return FileController{DB: db} // 创建file controller实例
}

// 创建文件（POST，用户ID，文件名，文件内容）
func (c FileController) Create(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID
	fileName := ctx.PostForm("name")
	fileContent := ctx.PostForm(("content"))

	// 数据验证
	if fileName == "" {
		response.Fail(ctx, nil, "数据验证错误，文件名必填")
		return
	}

	// 创建新文件
	newFile := model.File{
		Name:    fileName,
		UserID:  userId,
		Content: fileContent,
	}
	if err := c.DB.Create(&newFile).Error; err != nil {
		response.Fail(ctx, nil, "创建失败")
		return
	}

	// 返回创建结果
	response.Success(ctx, nil, "创建成功")
}

// 上传文件（PUT，用户ID，文件ID，文件obj）
func (c FileController) Upload(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID
	fileId := ctx.Params.ByName("id") // 从参数中获取
	file, err := ctx.FormFile("file")

	if err != nil {
		response.Fail(ctx, nil, "文件获取失败")
		return
	}

	// 检查文件是否存在
	var updateFile model.File
	err = c.DB.Where("id = ? AND user_id = ?", fileId, userId).First(&updateFile).Error
	if errors.Is(err, gorm.ErrRecordNotFound) { // 用户userId没有文件fileId
		response.Fail(ctx, nil, "文件不存在")
		return
	}

	// 获取文件内容
	payload, err := file.Open()
	byteContainer, err := ioutil.ReadAll(payload)
	fileContent := string(byteContainer)

	// 保存文件
	if err = c.DB.Model(&updateFile).Update("content", fileContent).Error; err != nil {
		response.Fail(ctx, nil, "上传失败")
		return
	}

	// 返回上传结果
	response.Success(ctx, gin.H{"file": dto.ToFileContentDto(updateFile)}, "上传成功")
}

// 写入数据库（PUT，用户ID，文件ID，文件内容）
func (c FileController) Save(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID
	fileId := ctx.Params.ByName("id") // 从参数中获取
	fileContent := ctx.PostForm("content")

	// 检查文件是否存在
	var updateFile model.File
	err := c.DB.Where("id = ? AND user_id = ?", fileId, userId).First(&updateFile).Error
	if errors.Is(err, gorm.ErrRecordNotFound) { // 用户userId没有文件fileId
		response.Fail(ctx, nil, "文件不存在")
		return
	}

	// 保存文件
	if err = c.DB.Model(&updateFile).Update("content", fileContent).Error; err != nil {
		response.Fail(ctx, nil, "保存失败")
		return
	}

	// 返回保存结果
	response.Success(ctx, nil, "保存成功")
}

// 重命名文件（PUT，用户ID，文件ID，新文件名）
func (c FileController) Update(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID
	fileId := ctx.Params.ByName("id") // 从参数中获取
	fileName := ctx.PostForm("name")

	// 数据验证
	if fileName == "" {
		response.Fail(ctx, nil, "数据验证错误，文件名必填")
		return
	}
	// 检查文件是否存在
	var updateFile model.File
	err := c.DB.Where("id = ? AND user_id = ?", fileId, userId).First(&updateFile).Error
	if errors.Is(err, gorm.ErrRecordNotFound) { // 用户userId没有文件fileId
		response.Fail(ctx, nil, "文件不存在")
		return
	}

	// 重命名文件
	if err = c.DB.Model(&updateFile).Update("name", fileName).Error; err != nil {
		response.Fail(ctx, nil, "重命名失败")
		return
	}

	// 返回重命名结果
	response.Success(ctx, nil, "重命名成功")
}

// 获取所有文件名（GET，用户ID）
func (c FileController) Show(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID

	// 查找用户的所有文件
	var showFiles []model.File
	if err := c.DB.Where("user_id = ?", userId).Find(&showFiles).Error; err != nil {
		response.Fail(ctx, nil, "查询失败")
		return
	}

	// 返回查询结果
	response.Success(ctx, gin.H{"files": dto.ToFileNameArrDto(showFiles)}, "查询成功")
}

// 读取文件内容（GET，用户ID，文件ID）
func (c FileController) Load(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID
	fileId := ctx.Params.ByName("id") // 从参数中获取

	// 读取用户userId的文件fileId
	var loadFile model.File
	if err := c.DB.Where("id = ? AND user_id = ?", fileId, userId).First(&loadFile).Error; err != nil {
		response.Fail(ctx, nil, "读取失败")
		return
	}

	// 返回查询结果
	response.Success(ctx, gin.H{"file": dto.ToFileContentDto(loadFile)}, "读取成功")
}

// 删除文件（DELETE，用户ID，文件ID）
func (c FileController) Delete(ctx *gin.Context) {
	// 获取参数
	user, _ := ctx.Get("user")
	userId := user.(model.User).ID
	fileId := ctx.Params.ByName("id") // 从参数中获取

	// 删除文件
	var deleteFile model.File
	if err := c.DB.Where("id = ? AND user_id = ?", fileId, userId).Delete(&deleteFile).Error; err != nil {
		response.Fail(ctx, nil, "删除失败")
		return
	}

	// 返回删除结果
	response.Success(ctx, nil, "删除成功")
}
